package com.geeaks.mybatis.generator.controller;

import com.geeaks.mybatis.generator.enums.EnumFXML;
import com.geeaks.mybatis.generator.view.AlertUtil;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Modality;
import javafx.stage.Stage;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.lang.ref.SoftReference;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

public abstract class BaseFXController implements Initializable {

	private static final Logger logger = LoggerFactory.getLogger(BaseFXController.class);

	private Stage primaryStage;

	private Stage dialogStage;

	private static Map<EnumFXML, SoftReference<? extends BaseFXController>> cacheNodeMap = new HashMap<>();

	public BaseFXController loadFXMLPage(String title, EnumFXML fxmlPage, boolean cache) {
		SoftReference<? extends BaseFXController> parentNodeRef = cacheNodeMap.get(fxmlPage);
		if (cache && parentNodeRef != null) {
			return parentNodeRef.get();
		}
		URL skeletonResource = Thread.currentThread().getContextClassLoader().getResource(fxmlPage.fxml);
		FXMLLoader loader = new FXMLLoader(skeletonResource);
		Parent loginNode;
		try {
			loginNode = loader.load();
			BaseFXController controller = loader.getController();
			dialogStage = new Stage();
			dialogStage.setTitle(title);
			dialogStage.initModality(Modality.APPLICATION_MODAL);
			dialogStage.initOwner(getPrimaryStage());
			dialogStage.setScene(new Scene(loginNode));
			dialogStage.setMaximized(false);
			dialogStage.setResizable(false);
			dialogStage.show();
			controller.setDialogStage(dialogStage);
			// put into cache map
			SoftReference<BaseFXController> softReference = new SoftReference<>(controller);
			cacheNodeMap.put(fxmlPage, softReference);
			return controller;
		} catch (IOException e) {
			logger.error(e.getMessage(), e);
			AlertUtil.showErrorAlert(e.getMessage());
		}
		return null;
	}

	public Stage getPrimaryStage() {
		return primaryStage;
	}

	public void setPrimaryStage(Stage primaryStage) {
		this.primaryStage = primaryStage;
	}

	public Stage getDialogStage() {
		return dialogStage;
	}

	public void setDialogStage(Stage dialogStage) {
		this.dialogStage = dialogStage;
	}

	public void showDialogStage() {
		if (dialogStage != null) {
			dialogStage.show();
		}
	}

	public void closeDialogStage() {
		if (dialogStage != null) {
			dialogStage.close();
		}
	}
}
